/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

package keystoretwo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Random;
// junit.jar
import junit.framework.Assert;
// bcprov-jdk15on-150.jar
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;


/**
 *
 * @author rmartinezch
 */
public class KeyStoreTwo {
    
    /**
     * @param args the command line arguments
     */
    
    static String pemFile = "D:/Data/Projects/certificates/pk.der";
//    @Test
    public static void main(String[] args) throws FileNotFoundException, CertificateException, IOException {
        
        /**
         * Carga del proveedor por defecto de servicios criptográficos Bouncy Castle
         */
        Provider bc = new BouncyCastleProvider();
        Security.insertProviderAt(bc, 1);
        
        // TODO code application logic here
        System.out.println("pemFile:" + pemFile);
        File f = new File(pemFile);
        if (!f.exists() || f.isDirectory()) {
            System.out.println("pem file wrong !!!");
            return;
        }
        
        try {
            /**
             * Ruta y destimo del repositorio PKCS#12
             */
            String storeName =  "D:/Data/Projects/certificates/outstore.p12";
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            /**
             * Certificado Padre
             */
            Certificate trustCert =  createCertificate("CN=CA", "CN=CA", publicKey, privateKey);
            /**
             * Cadena de Certificados Padre e Hijo
             */
            Certificate[] outChain = { createCertificate("CN=Client", "CN=CA", publicKey, privateKey), trustCert };
            
            KeyStore outStore = KeyStore.getInstance("PKCS12");
            outStore.load(null, "secret".toCharArray());
            outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);
            OutputStream outputStream = new FileOutputStream(storeName);
            /**
             * Creación del repositorio con la clave secreta suministrada
             */
            outStore.store(outputStream, "secret".toCharArray());
            outputStream.flush();
            outputStream.close();
            
            /**
             * verificación del contenido del repositorio creado
             */
            KeyStore inStore = KeyStore.getInstance("PKCS12");
            inStore.load(new FileInputStream(storeName), "secret".toCharArray());
            Key key = outStore.getKey("myKey", "secret".toCharArray());
            Assert.assertEquals(privateKey, key);
            
            Certificate[] inChain = outStore.getCertificateChain("mykey");
            Assert.assertNotNull(inChain);
            Assert.assertEquals(outChain.length, inChain.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AssertionError(e.getMessage());
        }
        
        
    }
    
    private static X509Certificate createCertificate(String dn, String issuer, PublicKey publicKey, PrivateKey privateKey) throws Exception {
        X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
        certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random().nextLong())));
        certGenerator.setIssuerDN(new X509Name(dn));
        certGenerator.setSubjectDN(new X509Name(dn));
        certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer!
        certGenerator.setNotBefore(Calendar.getInstance().getTime());
        certGenerator.setNotAfter(Calendar.getInstance().getTime());
        certGenerator.setPublicKey(publicKey);
        certGenerator.setSignatureAlgorithm("SHA1withRSA");
        X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC");
        return certificate;
    }
    
}
